#!/bin/bash
### BEGIN INIT INFO
# Provides:          firewallRoma
# Required-Start:    $syslog
# Required-Stop:     $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Firewall GW + QoS
# Description:
#
### END INIT INFO
#####################################################################
# Initialization Section
#####################################################################

LOGGER="/usr/bin/logger -p kern.info -t FIREWALL"

#---- Binary files location
IFC=/sbin/ifconfig
IPT=/sbin/iptables
TC=/sbin/tc
IP=/sbin/ip
ROUTE=/sbin/route

#ADSLs existentes - Interfaces al exterior
#	Jazztel		#Ono
#adsl_ifaces=(eth1 	eth2)
#adsl_ips=(10.100.9.10	172.29.0.10)
#adsl_gws=(10.100.9.1	172.29.0.1)
#adsl_weight=(4		3)
#adsl_upload=(500	1600) #En kbits

adsl_ifaces=(eth2 		eth3)
adsl_ips=(172.29.0.10	10.100.9.10)
adsl_gws=(172.29.0.1	10.100.9.1)
adsl_weight=(3		5)
adsl_upload=(1600	600) #En kbits

#Gateway por defecto
DEFAULT_GW="172.29.0.1"

#Interfaz que da a la red interna empresarial
IF_INT="eth0"
#Red Interna
NET_INT="192.168.9.0/24"

#Interfaz de la VPN
IF_VPN="tun0"
PORT_VPN="11949"


#QoS - Defino los % garantizados de ancho de banda por tipo de tráfico
#10 -> ssh, syn, DNS, VoIP--> PRIO 1
RATE_P1=30
#11 ->  VPN traffic --> PRIO 2
RATE_P2=30
#12 -> http, https --> PRIO 3
RATE_P3=20
#13 -> smtp, pop3, imap, news --> PRIO 4
RATE_P4=10
#14 ->ftp y resto del tráfico --> PRIO 5
RATE_P5=10


#Parámetros para las colas sfq
PERTURB=10
QUANTUM=25000


$LOGGER Initializing

#---- Functions to set the file to one or zero
enable  () { for file in $@; do echo 1 > $file; $LOGGER enabled $file;  done }
disable () { for file in $@; do echo 0 > $file; $LOGGER disabled $file; done }


do_get_vars () {
	test "$1" == "loadvars" && return 0
}

do_clean_ipt () {
	$LOGGER Clean rules and chains start

	$IPT -F
	$IPT -X
	$LOGGER IPTABLES rules and chains remove
	$IPT -t nat -F
	$IPT -t nat -X
	$LOGGER NAT rules and chains remove
	$IPT -t mangle -F
	$IPT -t mangle -X
	$LOGGER MANGLE rules and chains remove
	$IPT -t filter -F
	$IPT -t filter -X
	$LOGGER FILTER rules and chains remove

	$LOGGER Clean rules and chains end
}

do_clean_QoS () {
	$LOGGER Clean QoS filters start
	
	for ((n=0;n<${#adsl_ifaces[@]};n++)); do
		$TC -s qdisc del dev ${adsl_ifaces[n]} root
		$LOGGER Delete Q0S Classes in ${adsl_ifaces[n]}
	done
	$LOGGER Clean QoS filters end
}

do_clean_routes () {
	$LOGGER Clean ROUTES rules start
	
	$IP route del default 2>/dev/null
	$IP route flush cache

	$LOGGER Clean ROUTES rules end
}

do_set_policy () {
	# $1 - Table FILTER
	# $2 - Table NAT
	# $3 - Table mangle
	# $4 - Default
	$LOGGER Default Policy start
	
	#---- FILTER tables. Set default policy to $1
	$IPT -t filter -P INPUT   $1
	$IPT -t filter -P OUTPUT  $1
	$IPT -t filter -P FORWARD $1
	$LOGGER Set FILTER policy to $1

	#---- NAT tables. Set default policy to $2
	$IPT -t nat -P PREROUTING  $2
	$IPT -t nat -P OUTPUT      $2
	$IPT -t nat -P POSTROUTING $2
	$LOGGER Set NAT policy to $2

	#---- MANGLE tables. Set default policy to $3
	$IPT -t mangle -P PREROUTING  $3
	$IPT -t mangle -P INPUT       $3
	$IPT -t mangle -P FORWARD     $3
	$IPT -t mangle -P OUTPUT      $3
	$IPT -t mangle -P POSTROUTING $3
	$LOGGER Set default MANGLE policy to $3
	
	#---- DEFAULT tables. Set default policy to $4
	$IPT -P INPUT       $4
	$IPT -P FORWARD     $4
	$IPT -P OUTPUT      $4
	$LOGGER Set DEFAULT policy to $4
	
	$LOGGER Default Policy end
}



do_show_state () {
	echo " ------------ Estado del QoS ------------- "

	for ((n=0;n<${#adsl_ifaces[@]};n++)); do
		echo "---------- Clases ${adsl_ifaces[n]} ----------"
		$TC -s class show dev ${adsl_ifaces[n]}
	done

	echo " ----------- Reglas QoS-----------------"
	$IPT -t mangle -L T-QoS -v -x
	echo " "

	echo " ----------- Reglas generales -----------------"
	$IPT -nvL
	echo " "
}

do_network_subsystem_configuration () {
	#####################################################################
	# Network subsystem configuration
	#####################################################################

	$LOGGER net config start

	#---- Disable IP forwarding
	enable /proc/sys/net/ipv4/ip_forward

	#---- Disable response to broadcasts. You don't want yourself becoming a Smurf amplifier
	enable /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

	#---- Enable bad error message protection 
	enable /proc/sys/net/ipv4/icmp_ignore_bogus_error_responses 

	#---- Turn on reverse path filtering. Safer, but breaks asymetric routing and/or IPSEC
	enable /proc/sys/net/ipv4/conf/*/rp_filter

	#---- Don't accept source routed packets. Source routing is rarely used for legitimate purposes
	disable /proc/sys/net/ipv4/conf/*/accept_source_route

	#---- Disable ICMP redirect acceptance which can be used to alter your routing tables
	disable /proc/sys/net/ipv4/conf/*/accept_redirects

	#---- As we don't accept redirects, don't send Redirect messages either
	disable /proc/sys/net/ipv4/conf/*/send_redirects

	#---- Ignore packets with impossible addresses
	disable /proc/sys/net/ipv4/conf/*/log_martians

	#---- Protect against wrapping sequence numbers and aid round trip time measurement
	enable /proc/sys/net/ipv4/tcp_timestamps

	#---- Help against syn-flood DoS or DDoS attacks using particular choices of initial TCP sequence numbers
	enable /proc/sys/net/ipv4/tcp_syncookies

	#---- Use Selective ACK which can be used to signify that specific packets are missing
	disable /proc/sys/net/ipv4/tcp_sack

	$LOGGER net config end
}

do_dynamic_modules_configuration () {
	#####################################################################
	# Dynamic modules section
	#####################################################################

	$LOGGER module loading start
	#----  Load needed modules - comment and uncomment as needed
	modprobe nf_conntrack
	modprobe nf_conntrack_ipv4
	modprobe nf_nat
	modprobe nf_conntrack_ipv6
	modprobe nf_conntrack_amanda
	modprobe nf_nat_amanda
	modprobe nf_conntrack_h323
	modprobe nf_nat_h323
	modprobe nf_conntrack_ftp
	modprobe nf_nat_ftp
	modprobe nf_conntrack_netbios_ns
	modprobe nf_conntrack_irc
	# modprobe nf_nat_irc
	modprobe nf_conntrack_proto_dccp
	# modprobe nf_nat_proto_dccp
	modprobe nf_conntrack_netlink
	modprobe nf_conntrack_pptp
	# modprobe nf_nat_pptp
	modprobe nf_conntrack_proto_udplite
	# modprobe nf_nat_proto_udplite
	modprobe nf_conntrack_proto_gre
	# modprobe nf_nat_proto_gre
	modprobe nf_conntrack_proto_sctp
	# modprobe nf_nat_proto_sctp
	modprobe nf_conntrack_sane
	modprobe nf_conntrack_sip
	modprobe nf_nat_sip
	modprobe nf_conntrack_tftp
	modprobe nf_nat_tftp
	modprobe nf_nat_snmp_basic

	$LOGGER module loading end
}


do_filter_configuration () {

	
	$LOGGER filter loading start

	#---- Jump here from TCPFLAGS -- log and drop packets with bad flags
	$IPT -N BADFLAGS
	$IPT -A BADFLAGS -j LOG --log-level WARNING --log-prefix "IPT TCPFLAGS: "
	$IPT -A BADFLAGS -j DROP

	#---- Create new chain for checking TCP flags
	$IPT -N TCPFLAGS

	#---- Log and discard packets with invalid state
	$IPT -A TCPFLAGS -p tcp -m state --state INVALID -j LOG --log-level WARNING --log-prefix "IPT INVALID: "
	$IPT -A TCPFLAGS -p tcp -m state --state INVALID -j DROP

	#---- Discard if first packet on a conversation and no SYN flag
	$IPT -A TCPFLAGS -p tcp ! --syn -m state --state NEW -j BADFLAGS

	#---- Help to prevent TCP spoofing by sequence number prediction attack
	$IPT -A TCPFLAGS -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j REJECT --reject-with tcp-reset

	#---- FIN, PSH or URG should always be accompained by ACK
	$IPT -A TCPFLAGS -p tcp --tcp-flags ACK,FIN FIN -j BADFLAGS
	$IPT -A TCPFLAGS -p tcp --tcp-flags ACK,PSH PSH -j BADFLAGS
	$IPT -A TCPFLAGS -p tcp --tcp-flags ACK,URG URG -j BADFLAGS

	#---- FIN, SYN and RST are mutually exclusive
	$IPT -A TCPFLAGS -p tcp --tcp-flags FIN,RST FIN,RST -j BADFLAGS
	$IPT -A TCPFLAGS -p tcp --tcp-flags SYN,FIN SYN,FIN -j BADFLAGS
	$IPT -A TCPFLAGS -p tcp --tcp-flags SYN,RST SYN,RST -j BADFLAGS

	#---- Packets with no flags are invalid
	$IPT -A TCPFLAGS -p tcp --tcp-flags ALL NONE -j BADFLAGS
	
	#---- Perform tcp flags checking for every packet
	$IPT -A INPUT  -p tcp -j TCPFLAGS
	$IPT -A OUTPUT -p tcp -j TCPFLAGS

	$LOGGER Active DROP and LOG packets with badflags, invalid or reject
	
	#---- Allow anything incomming over loopback
	$IPT -A INPUT -i lo -j ACCEPT
	$LOGGER Allowed anything incomming over the loopback interface

	#---- Allow outgoing packets generated in this machine
	$IPT -A OUTPUT -p tcp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
	$IPT -A OUTPUT -p udp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
	$IPT -A OUTPUT -p icmp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
	$LOGGER Allow outgoing packets generated in this machine

	#---- Allow ongoing conversations (stateful filtering)
	$IPT -A INPUT -p tcp  -m state --state RELATED,ESTABLISHED -j ACCEPT
	$IPT -A INPUT -p udp  -m state --state RELATED,ESTABLISHED -j ACCEPT
	$IPT -A INPUT -p icmp -m state --state RELATED,ESTABLISHED -j ACCEPT
	$LOGGER Allow ongoing conversations - stateful filtering -

	#---- Accept (and answer) PING requests, but no faster than 1 per second. Comment if not needed
	$IPT -A INPUT -p icmp -m state --state NEW --icmp-type echo-request -m limit --limit 1/s --limit-burst 1 -j ACCEPT
	$LOGGER Accept - and answer - PING requests, but no faster than 1 per second.

	#---- Create a new chain for SSH packets
	$IPT -N SSH
	#---- Allow only 3 new incoming ssh connections per minute
	$IPT -A SSH -m limit --limit 5/minute --limit-burst 10 -j ACCEPT
	#---- Log and drop faster connection attempts
	$IPT -A SSH -j LOG --log-level WARNING --log-prefix "IPT SSH connection too fast: "
	$IPT -A SSH -j DROP
	#---- Allow incoming ssh
	$IPT -A INPUT -p tcp --dport 22 -m state --state NEW -j SSH
	$LOGGER Allow only 3 new incoming SSH connections per minute and log FAILS

	#---- Allow anything incomming, outcomming and forward over VPN interface
	$IPT -A INPUT -i ${IF_VPN} -j ACCEPT
	$IPT -A FORWARD -i ${IF_VPN} -o ${IF_INT} -j ACCEPT
	$IPT -A FORWARD -i ${IF_INT} -o ${IF_VPN} -j ACCEPT
	$LOGGER Allowed anything incomming, outcomming and forward over the VPN interface

	#---- Allow outgoing connection from inside net to Internet
	for ((n=0;n<${#adsl_ifaces[@]};n++)); do  
		$IPT -A FORWARD -i ${IF_INT} -s ${NET_INT} -o ${adsl_ifaces[n]}  -j ACCEPT
	done
	$LOGGER Allow outgoing connection from inside net to Internet

	#---- Allow established connections comming from the outside
	for ((n=0;n<${#adsl_ifaces[@]};n++)); do  
		$IPT -A FORWARD -i ${adsl_ifaces[n]} -o ${IF_INT} -m state --state ESTABLISHED,RELATED -j ACCEPT
	done
	$LOGGER Allow established connections comming from the outside

	#####################################################################
	# Specific Services
	#####################################################################
	#---- DNS Service -------------------------
	$IPT -A INPUT -p tcp --dport 53 -s ${NET_INT} -m state --state NEW -j ACCEPT
	$IPT -A INPUT -p udp --dport 53 -s ${NET_INT} -m state --state NEW -j ACCEPT
	$LOGGER Allowed service DNS requests from de net

	#---- DHCPD Service -------------------------
	$IPT -A INPUT -i ${IF_INT} -p udp --dport 68 -m state --state NEW -j ACCEPT
	#$IPT -A INPUT -p udp --sport 68 -m state --state NEW -j ACCEPT
	$LOGGER Allowed service DHCPD

	#---- NTPD Service -------------------------
	$IPT -A INPUT -i ${IF_INT} -p udp --dport 123 -m state --state NEW -j ACCEPT
	$LOGGER Allowed service NTPD

	#---- Nagios Service -------------------------
	$IPT -A INPUT -p tcp --dport 5666 -s 10.10.9.1/32 -m state --state NEW -j ACCEPT
	$LOGGER Allowed service Nagios nrpe

	#---- Copias de seguridad - Bacula File Server
	$IPT -A INPUT -i ${IF_INT} -p tcp --dport 9102 -s ${NET_INT} -j ACCEPT
	$LOGGER Allowed Bacula FD
	

	#---- Bloqueamos toda conexión saliente al 25 que no sea OVH
	#OVH
	#Afecta a las máquinas que hacemos nat
	$IPT -A FORWARD -d 94.23.80.83/32 -p tcp -m tcp --dport 25 -j ACCEPT 
	#Afecta a el servidor 
	$IPT -A OUTPUT -d 94.23.80.83/32 -p tcp -m tcp --dport 25 -j ACCEPT 
	#Rechaza todo lo que vaya al puerto 25 
	$IPT -A OUTPUT -p tcp -m tcp --dport 25 -j LOG --log-prefix "Conexion p 25 - O - NO OVH: " 
	$IPT -A FORWARD -p tcp -m tcp --dport 25 -j LOG --log-prefix "Conexion p 25 - F - NO OVH: " 
	$IPT -A FORWARD -p tcp -m tcp --dport 25 -j DROP 
	$IPT -A OUTPUT -p tcp -m tcp --dport 25 -j DROP 


	#####################################################################
	# Cosas que no queremos que se marquen en el Log
	#####################################################################
	$IPT -A INPUT -i ${IF_INT} -s ${NET_INT} -p udp -d 192.168.9.255 -j DROP
	$IPT -A INPUT -i ${IF_INT} -s ${NET_INT} -p udp -d 255.255.255.255 -j DROP


	#####################################################################
	# Log ALL
	#####################################################################

	#---- Log (and drop by default) any other packet
	$IPT -A INPUT   -j LOG --log-level WARNING --log-prefix "IPT INPUT packet died: "
	$IPT -A OUTPUT  -j LOG --log-level WARNING --log-prefix "IPT OUTPUT packet died: "
	$IPT -A FORWARD -j LOG --log-level WARNING --log-prefix "IPT FORWARD packet died: "
	$LOGGER Log and drop any other packet

	
	$LOGGER filter loading end
}


do_QoS () {
	$LOGGER QoS loading start

	for((n=0;n<${#adsl_ifaces[@]};n++)); do
		#Levantamos los interfaces
		$IFC ${adsl_ifaces[n]} ${adsl_ips[n]} netmask 255.255.255.0 up
		#Borramos todo lo anterior
		#Borramos la tabla de rutas
		$IP route flush table adsl$((n+1)) 2>/dev/null
		#Borramos las reglas
		$IP rule del from ${adsl_ips[n]} table adsl$((n+1)) 2>/dev/null
		#Borramos las colas creadas en el interfaz de salida
		$TC qdisc del dev ${adsl_ifaces[n]} root 2>/dev/null
		#Creo la cola con prioridad de servicio	
		$TC qdisc add dev ${adsl_ifaces[n]} root handle 1: htb default 13

		$TC class add dev ${adsl_ifaces[n]} parent 1: classid 1:1 htb rate ${adsl_upload[n]}kbit ceil ${adsl_upload[n]}kbit

		$TC class add dev ${adsl_ifaces[n]} parent 1:1 classid 1:10 htb rate $((adsl_upload[n] * RATE_P1 / 100))kbit ceil ${adsl_upload[n]}kbit prio 1
		$TC class add dev ${adsl_ifaces[n]} parent 1:1 classid 1:11 htb rate $((adsl_upload[n] * RATE_P2 / 100))kbit ceil ${adsl_upload[n]}kbit prio 2
		$TC class add dev ${adsl_ifaces[n]} parent 1:1 classid 1:12 htb rate $((adsl_upload[n] * RATE_P3 / 100))kbit ceil ${adsl_upload[n]}kbit prio 3
		$TC class add dev ${adsl_ifaces[n]} parent 1:1 classid 1:13 htb rate $((adsl_upload[n] * RATE_P4 / 100))kbit ceil ${adsl_upload[n]}kbit prio 4
		$TC class add dev ${adsl_ifaces[n]} parent 1:1 classid 1:14 htb rate $((adsl_upload[n] * RATE_P5 / 100))kbit ceil ${adsl_upload[n]}kbit prio 5

		$TC qdisc add dev ${adsl_ifaces[n]} parent 1:10 handle 100: sfq perturb ${PERTURB} quantum ${QUANTUM}
		$TC qdisc add dev ${adsl_ifaces[n]} parent 1:11 handle 110: sfq perturb ${PERTURB} quantum ${QUANTUM}
		$TC qdisc add dev ${adsl_ifaces[n]} parent 1:12 handle 120: sfq perturb ${PERTURB} quantum ${QUANTUM}
		$TC qdisc add dev ${adsl_ifaces[n]} parent 1:13 handle 130: sfq perturb ${PERTURB} quantum ${QUANTUM}
		$TC qdisc add dev ${adsl_ifaces[n]} parent 1:14 handle 140: sfq perturb ${PERTURB} quantum ${QUANTUM}


		$TC filter add dev ${adsl_ifaces[n]} parent 1: protocol ip prio 1 handle 60 fw classid 1:10
		$TC filter add dev ${adsl_ifaces[n]} parent 1: protocol ip prio 2 handle 61 fw classid 1:11
		$TC filter add dev ${adsl_ifaces[n]} parent 1: protocol ip prio 3 handle 62 fw classid 1:12
		$TC filter add dev ${adsl_ifaces[n]} parent 1: protocol ip prio 4 handle 63 fw classid 1:13
		$TC filter add dev ${adsl_ifaces[n]} parent 1: protocol ip prio 5 handle 64 fw classid 1:14

		#Creo las tablas de ruteo copiando la tabla main y cambiando el default gw
		while read line ; do
			test -z "${line##default*}" && continue
			test -z "${line##nexthop*}" && continue
			$IP route add $line table adsl$((n+1))
		done < \
		<($IP route ls default table main)
		$IP route add default table adsl$((n+1)) proto static via ${adsl_gws[n]} dev ${adsl_ifaces[n]}
		#Creamos la regla de ruteo para salir por cada tabla según el origen
		$IP rule add from ${adsl_ips[n]} table adsl$((n+1))
		#Guardamos el path para gestionar el balanceo
		multipath="$multipath nexthop via ${adsl_gws[n]} dev ${adsl_ifaces[n]} weight ${adsl_weight[n]}"
	done

	
	#Limpiamos las rutas
	do_clean_routes

	#Creamos el default gw con el multipath en la tabla main
	$IP route add default proto static $multipath
	#Refrescamos la cache de las tablas de ruteo
	$IP route flush cache

	#Limpiamos todas las reglas de iptables
	do_clean_ipt

	#Activamos NAT
	do_NAT

	# Para mantener le conexión
	# ############ CONNTRACK ############  
	# restauro la marka en PREROUTING antes de la decisión de ruteo.  
	$IPT -t mangle -A PREROUTING -j CONNMARK --restore-mark  
   
	# # CONNTRACK para el multipath  
	# # creo una tabla aparte  
	$IPT -t mangle -N my_connmark  
	# y hago pasar los packetes que aún nunca fueron markados  
	# (siempre serán paquetes que inician una conexión)  
	$IPT -t mangle -A FORWARD -m mark --mark 0 -j my_connmark  
	# una vez procesado, borro la marka por si quiero usar las markas para otras cosas  
	# como x ej QoS y control ancho de banda  
	$IPT -t mangle -A FORWARD -j MARK --set-mark 0x0  

	# y ahora el contenido de la tabla aparte: my_conntrack  
	# para la LAN no me hace falta conntrack ya que tengo una sola interfaz  
	$IPT -t mangle -A my_connmark -o ${IF_INT} -j RETURN
	# por cada conexión  
	for((n=0;n<${#adsl_ifaces[@]};n++)); do  
		#asocio una marka a cada interfaz  
		$IPT -t mangle -A my_connmark -o ${adsl_ifaces[n]} -j MARK --set-mark 0x$((n+1))  
		$IPT -t mangle -A my_connmark -i ${adsl_ifaces[n]} -j MARK --set-mark 0x$((n+1))  
	done  
	# la guardo para después poder hacer el –restore-mark en PREROUTING  
	$IPT -t mangle -A my_connmark -j CONNMARK --save-mark  
	# por ultimo uso ip ru para hacer que el packete use la tabla de ruteo que le corresponde  
	for ((n=0;n<${#adsl_ifaces[@]};n++)); do  
		$IP ru del fwmark 0x$((n+1)) table adsl$((n+1)) 2>/dev/null  
		$IP ru add fwmark 0x$((n+1)) table adsl$((n+1))  
	done  

	#Creamos el marcado QoS 
	$IPT -t mangle -N T-QoS
	$IPT -t mangle -I POSTROUTING -j T-QoS 

	#Marcaje de paquetes bajada
	#TCP con el bit SYN activado (principio de conexion)
	$IPT -t mangle -A T-QoS -p tcp --syn -j MARK --set-mark 60
	$IPT -t mangle -A T-QoS -p tcp --syn -j RETURN 

	#ICMP
	$IPT -t mangle -A T-QoS -p icmp -j MARK --set-mark 60
	$IPT -t mangle -A T-QoS -p icmp -j RETURN

	#VoIP
	$IPT -t mangle -A T-QoS -p udp --dport 3000 -j MARK --set-mark 60 
	$IPT -t mangle -A T-QoS -p udp --dport 3000 -j RETURN
	$IPT -t mangle -A T-QoS -p udp --sport 3000 -j MARK --set-mark 60 
	$IPT -t mangle -A T-QoS -p udp --sport 3000 -j RETURN
	$IPT -t mangle -A T-QoS -p udp --dport 5060 -j MARK --set-mark 60 
	$IPT -t mangle -A T-QoS -p udp --dport 5060 -j RETURN
	$IPT -t mangle -A T-QoS -p udp --sport 5060 -j MARK --set-mark 60 
	$IPT -t mangle -A T-QoS -p udp --sport 5060 -j RETURN


	#SSH
	$IPT -t mangle -A T-QoS -p tcp --dport 22 -j MARK --set-mark 60 
	$IPT -t mangle -A T-QoS -p tcp --dport 22 -j RETURN
	$IPT -t mangle -A T-QoS -p tcp --sport 22 -j MARK --set-mark 60 
	$IPT -t mangle -A T-QoS -p tcp --sport 22 -j RETURN 

	#DNS
	$IPT -t mangle -A T-QoS -p udp --dport 53 -j MARK --set-mark 60
	$IPT -t mangle -A T-QoS -p udp --dport 53 -j RETURN
	$IPT -t mangle -A T-QoS -p udp --sport 53 -j MARK --set-mark 60
	$IPT -t mangle -A T-QoS -p udp --sport 53 -j RETURN

	#VPN Traffic 
	$IPT -t mangle -A T-QoS -p udp --dport ${PORT_VPN} -j MARK --set-mark 61
	$IPT -t mangle -A T-QoS -p udp --dport ${PORT_VPN} -j RETURN
	$IPT -t mangle -A T-QoS -p udp --sport ${PORT_VPN} -j MARK --set-mark 61
	$IPT -t mangle -A T-QoS -p udp --sport ${PORT_VPN} -j RETURN



	#HTTP y HTTPS
	$IPT -t mangle -A T-QoS -p tcp --dport 80 -j MARK --set-mark 62
	$IPT -t mangle -A T-QoS -p tcp --dport 80 -j RETURN
	$IPT -t mangle -A T-QoS -p tcp --sport 80 -j MARK --set-mark 62
	$IPT -t mangle -A T-QoS -p tcp --sport 80 -j RETURN
	$IPT -t mangle -A T-QoS -p tcp --dport 443 -j MARK --set-mark 62
	$IPT -t mangle -A T-QoS -p tcp --dport 443 -j RETURN
	$IPT -t mangle -A T-QoS -p tcp --sport 443 -j MARK --set-mark 62
	$IPT -t mangle -A T-QoS -p tcp --sport 443 -j RETURN

	#FTP 
	$IPT -t mangle -A T-QoS -p tcp --dport 20:21 -j MARK --set-mark 64
	$IPT -t mangle -A T-QoS -p tcp --dport 20:21 -j RETURN
	$IPT -t mangle -A T-QoS -p tcp --sport 20:21 -j MARK --set-mark 64
	$IPT -t mangle -A T-QoS -p tcp --sport 20:21 -j RETURN

	#Correo
	#POP3
	$IPT -t mangle -A T-QoS -p tcp --dport 110 -j MARK --set-mark 63
	$IPT -t mangle -A T-QoS -p tcp --dport 110 -j RETURN
	$IPT -t mangle -A T-QoS -p tcp --sport 110 -j MARK --set-mark 63
	$IPT -t mangle -A T-QoS -p tcp --sport 110 -j RETURN

	#IMAP
	$IPT -t mangle -A T-QoS -p tcp --dport 143 -j MARK --set-mark 63
	$IPT -t mangle -A T-QoS -p tcp --dport 143 -j RETURN
	$IPT -t mangle -A T-QoS -p tcp --sport 143 -j MARK --set-mark 63
	$IPT -t mangle -A T-QoS -p tcp --sport 143 -j RETURN

	#IMAPS
	$IPT -t mangle -A T-QoS -p tcp --dport 993 -j MARK --set-mark 63
	$IPT -t mangle -A T-QoS -p tcp --dport 993 -j RETURN
	$IPT -t mangle -A T-QoS -p tcp --sport 993 -j MARK --set-mark 63
	$IPT -t mangle -A T-QoS -p tcp --sport 993 -j RETURN

	#SMTP
	$IPT -t mangle -A T-QoS -p tcp --dport 25 -j MARK --set-mark 63
	$IPT -t mangle -A T-QoS -p tcp --dport 25 -j RETURN
	$IPT -t mangle -A T-QoS -p tcp --sport 25 -j MARK --set-mark 63
	$IPT -t mangle -A T-QoS -p tcp --sport 25 -j RETURN


	#VPN por tun0
	$IPT -t mangle -A T-QoS  -o tun0  -j MARK --set-mark 61
	$IPT -t mangle -A T-QoS -o tun0  -j RETURN


	#Resto del tráfico de subida
	$IPT -t mangle -A T-QoS -j MARK --set-mark 64

}

do_NAT () {
	#--- Allow NAT from inside net
	for ((n=0;n<${#adsl_ifaces[@]};n++)); do  
		$IPT -t nat -A POSTROUTING -o ${adsl_ifaces[n]} -s ${NET_INT} -j MASQUERADE  
	done
	$LOGGER Allow NAT from inside net
}


do_start () {
	$LOGGER STARTING QoS + Fw start
	do_network_subsystem_configuration
	do_dynamic_modules_configuration
	do_QoS
	do_set_policy DROP ACCEPT ACCEPT ACCEPT
	do_filter_configuration
	do_set_policy DROP ACCEPT ACCEPT DROP
	$LOGGER STARTING QoS + Fw end


}


do_stop () {
	$LOGGER STOPPING QoS + Fw start
	
	do_set_policy ACCEPT ACCEPT ACCEPT ACCEPT
	do_clean_QoS
	do_clean_ipt
	do_clean_routes
	enable /proc/sys/net/ipv4/ip_forward
	do_NAT
	$LOGGER Define default gw ${DEFAULT_GW}
	$ROUTE add default gw ${DEFAULT_GW}
	
	$LOGGER STOPPING QoS + Fw end
}


do_watchdog () {
	#A to M ROOT DNS world servers ip address
	#I choose those that seems to accept icmp-echo-requests
	root_dnservers="B C D E F I J K L M"
	multipath_total=0
	log_file="/var/log/adsl_watchdog.log"
	for((n=0;n<${#adsl_ifaces[@]};n++)); do
        	pong=0
        	for letter in $root_dnservers; do
                	if(ping -n -c1 -W2 $letter.root-servers.net -I ${adsl_ips[n]} &>/dev/null);then
                        	pong=1
                        	# el doble espacio antes de dev _does_mather_
                        	multipath="$multipath nexthop via ${adsl_gws[n]}  dev ${adsl_ifaces[n]} weight ${adsl_weight[n]}"
                        	let multipath_total+=1
                        	break
                	fi
        	done
        	#if no one answers
        	if [[ $pong == 0 ]];then
                	#ejemplo telnet y reset, para un zyxel (opciones 24, 4 y 21)
                	# user=user;pass=pass; 
                	#echo -e "$user\n$pass\n$24\n4\n21\n" | telnet ${adsl_gws[n]} &
                	# ejemplo hacer sonar el beep
                	#echo -e "\a"
                	# ejemplo mail
                	# echo “ip:${adsl_ips[n} iface:${adsl_ifaces[n]}” | mail -s “se cayo la conexión ${adsl_ips[n]}” someone@foo.bar
                	# logueo para futuro análisis
                	echo `date +%d/%m/%y-%T`" la conexion con ${adsl_gws[n]} esta down" >> ${log_file}
    		fi
	done

	#si todos estan caidos dejo todo como estaba
	test -z "${multipath}" && echo `date +%d/%m/%y-%T`" -0- Todas las conexiones están caídas" >> ${log_file}   && exit 1

	n_conex=`echo $multipath | tr ' ' '\n' | grep -c via`
	n=$((n_conex * 100 / ${#adsl_ifaces[@]}))

	# cargo en $route el multipath actual
	while read line ;do
        	test -z "${line##default*}" && begin=1
        	test "$begin" == 1 && route="$route ${line}"
	done < \
	<(/sbin/ip route ls)

	# armo el multipath de los que estan up para poder comparar
	# tengo que preguntar xq si hay solo un enlace up, la sintaxis cambia
	if [[ $multipath_total > 1 ]];then
        	# el doble espacio antes de proto _does_mather_
        	route_multipath=" default  proto static${multipath}"
	else
        	route_multipath=${multipath#nexthop }
        	route_multipath=${route_multipath% weight*}
        	route_multipath=" default ${route_multipath/ dev/ dev} proto static"
	fi

	# Ya tengo los 2 multipath, ahora puedo comparar
	if [[ "$route" != "$route_multipath" ]];then
        	# si no son iguales, es hora de cambiar el default gateway
        	ip route chg default proto static $multipath
        	ip route flush cache
        	echo `date +%d/%m/%y-%T`" -$n- cambiando default gateway a $multipath" >> ${log_file}
	else
		echo `date +%d/%m/%y-%T`" -$n- Todo se mantiene estable" >> ${log_file}
	fi
}


case "$1" in
	start)
		do_stop
		sleep 2
		do_start
		;;
	stop)
		do_stop
		;;
	restart)
		do_stop
		sleep 2
		do_start
		;;
	status)
		do_show_state
		;;
	watchdog)
		do_watchdog
		;;
	*)
		N=/etc/init.d/$NAME
		echo "Usage: $N {start|stop|restart|watchdog|status}" >&2
		exit 1
		;;
esac


